﻿using System.Diagnostics;
using Microsoft.EntityFrameworkCore;
using ST.Core;
using ST.Data;
using ST.ModelVM.ProtocolDefine;
using ST.ModelVM.ProtocolSimHost;
using ST.ModelVM.ProtocolSimLog;

namespace ST.Receiver.Tasks
{
    public class TransMain : BackgroundService
    {
        public static TransMain Instance;
        ILogger<TransMain> _logger;
        IDbContextFactory<AppDbContext> _fact; 
        AppDbContext _DB;
        IRepository<ST.Data.ProtocolDefine> _IRepositoryProtocolDefine;
        IRepository<ST.Data.ProtocolSim> _IRepositoryProtocolSim;
        IRepository<ST.Data.ProtocolSimHost> _IRepositoryProtocolSimHost;
        IRepository<ST.Data.ProtocolSimLog> _IRepositoryProtocolSimLog;
        List<SimWorker> ltrans=new List<SimWorker>();
        CancellationToken stoppingToken;

        List<ProtocolSimLog> LstProtocolSimLog=new List<ProtocolSimLog>();

        public TransMain(ILogger<TransMain> logger

            )
        { 
            _logger = logger;
            Instance = this;


        }

        protected override async System.Threading.Tasks.Task ExecuteAsync(CancellationToken stoppingToken)
        {
            this.stoppingToken = stoppingToken;   

            _fact = ST.Core.Util.ServicesUtil.GetScopeRequiredService<IDbContextFactory<AppDbContext>>();
            _DB = _fact.CreateDbContext();
            _IRepositoryProtocolDefine = ST.Core.Util.ServicesUtil.GetScopeRequiredService<IRepository<ST.Data.ProtocolDefine>>();
            _IRepositoryProtocolSim = ST.Core.Util.ServicesUtil.GetScopeRequiredService<IRepository<ST.Data.ProtocolSim>>();
            _IRepositoryProtocolSimHost = ST.Core.Util.ServicesUtil.GetScopeRequiredService<IRepository<ST.Data.ProtocolSimHost>>();
            _IRepositoryProtocolSimLog = ST.Core.Util.ServicesUtil.GetScopeRequiredService<IRepository<ST.Data.ProtocolSimLog>>();
 

            _logger.LogInformation("通讯主任务开始。。。。");

            foreach (var item in _IRepositoryProtocolSim.GetAll().ToList())
            {
                await StartSimAsync(item.Id);
            }
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    await BatchSaveProtocolSimLog();

                    await Task.Delay(5000, stoppingToken);
                }
                catch (Exception ex)
                {

                }
            }
            await BatchSaveProtocolSimLog();
            _logger.LogInformation("通讯主任务结束");
        }
        public async Task BatchSaveProtocolSimLog()
        {
            List<ProtocolSimLog> l = null;
            lock (LstProtocolSimLog)
            {
                l = new List<ProtocolSimLog>(LstProtocolSimLog);
                LstProtocolSimLog.Clear();
            }
            if (l.Count == 0)
            {
                return;
            }
            Stopwatch sw = Stopwatch.StartNew();
            _IRepositoryProtocolSimLog.DB.AddRange(l);
            await _IRepositoryProtocolSimLog.DB.SaveChangesAsync();
            _IRepositoryProtocolSimLog.DB.ChangeTracker.Clear();
            sw.Stop();
            _logger.LogInformation($"BatchSaveProtocolSimLog:数量{l.Count} 耗时：{sw.ElapsedMilliseconds}");

 

        }
        public ProtocolSimLog AddSimLog(Int64 SimId, Int64 ProtocolSimHostId, string Lx, byte[] Data, string memo)
        {
            var m = new Data.ProtocolSimLog
            {
                Id = ST.Core.Util.IdUtil.NextId(),
                ProtocolSimId = SimId,
                ProtocolSimHostId = ProtocolSimHostId,               
                Lx = Lx,
                Data = ST.Core.Util.ByteUtil.ToHexString(Data),
                Memo = memo,
                Dt = DateTime.Now,
            };
            lock (LstProtocolSimLog)
            {
                LstProtocolSimLog.Add(m);
            }
             
            return m;
        }
        public async Task StartSimAsync(Int64 simid)
        {
            var t1 = ltrans.Where(a => a.Id == simid).FirstOrDefault();
            if (t1 != null)
            {
                return;
            }
            _IRepositoryProtocolSim.DB.ChangeTracker.Clear();
            _IRepositoryProtocolDefine.DB.ChangeTracker.Clear();
            _IRepositoryProtocolSimHost.DB.ChangeTracker.Clear();
            var msim = _IRepositoryProtocolSim.GetById(simid);
            var mdefine = _IRepositoryProtocolDefine.GetById(msim.ProtocolDefineId);
            var l=_IRepositoryProtocolSimHost.GetAll().Where(a=>a.ProtocolSimId == simid).ToList();
            var wk = ST.Core.Util.ServicesUtil.GetScopeRequiredService<ST.Receiver.Tasks.SimWorker>();

            wk.Id= simid;   
            wk.ProtocolSim=msim;
            wk.ProtocolDefine=mdefine;  
            wk.ProtocolSimHostList = l;
            await wk.StartAsync(this.stoppingToken);

            ltrans.Add(wk);


        }
        public async Task StopSimAsync(Int64 simid)
        {
            var t = ltrans.Where(a => a.Id == simid).FirstOrDefault();
            if (t != null)
            {
                await t.StopAsync(this.stoppingToken);
                ltrans.Remove(t);
            }
        }
        public string GetRunState(Int64 simid)
        {
            var t = ltrans.Where(a => a.Id == simid).FirstOrDefault();
            if (t != null)
            {
                return "启动";
            }
            return "停止";
        }



        #region WEB
        public PageResult<EquipmentAttributeVM> DataPage(ProtocolSimHostDataQM qm)
        {
            var mhost = _IRepositoryProtocolSimHost.GetById(qm.ProtocolSimHostId);
            var mworker= ltrans.Where(a=>a.Id==mhost.ProtocolSimId).FirstOrDefault();
            if (mworker == null)
            {
                return new PageResult<EquipmentAttributeVM>();
            }
            var msimhost=mworker.SimHostWorkerList.Where(a => a.ProtocolSimHost.Id == qm.ProtocolSimHostId).FirstOrDefault();
            var r = new PageResult<EquipmentAttributeVM>();
            r.Total = msimhost.EquipmentAttributes.Count;
            var q = msimhost.EquipmentAttributes.AsQueryable();
            if (!string.IsNullOrEmpty(qm.Key))
            {
                q=q.Where(a=>a.DeviceName.Contains(qm.Key));
            }
            r.Data = q
                .OrderBy(a => a.DeviceCode)
                .ThenBy(a => a.PropCode)
                .Skip((qm.Page - 1) * qm.PageSize)
                .Take(qm.PageSize)
                .ToList();
            return r;
        }

        public async Task<int> CmdAsync(ProtocolCmdVM qm)
        {
            var mhost = _IRepositoryProtocolSimHost.GetById(qm.ProtocolSimHostId);
            var mworker = ltrans.Where(a => a.Id == mhost.ProtocolSimId).FirstOrDefault();
            var r= await mworker.CmdAsync(qm);
            _logger.LogInformation($"执行指令：{mhost.HostName} {qm.Cmd} 结果：{r}");
            return r;
        }
        #endregion

    }
}
